home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include <dos.h>
- #include <string.h>
- #include <bios.h>
- #include <conio.h>
- #include <mem.h>
- #include <dos.h>
- #include <i86.h>
-
-
- /*
- m
- ╔═════════════════════════════════════════════════════════════════╗
- ║ █▓▒░ WordUp Graphics Toolkit V5.0 ░▒▓█ ║
- ║ Source Code -- Public Domain (No Copyright) ║
- ╟─────────────────────────────────────────────────────────────────╢
- ║ Module: wlink.c ║
- ║ Contains: wlink_answer, wlink_dial, wlink_flush_incoming, ║
- ║ wlink_flush_outgoing, wlink_getuart, ║
- ║ wlink_getvector, wlink_hangup_modem, ║
- ║ wlink_initmodem, wlink_initport, ║
- ║ wlink_modemcommand, wlink_modemresponse, ║
- ║ wlink_read_byte, wlink_shutdownport, ║
- ║ wlink_write_buffer ║
- ║ ║
- ║ Last Revised: March 31, 1995 ║
- ║ ║
- ║ Most of this source code was adapted from the ser4 code ║
- ║ which was originally released by Russell Gilbert. ║
- ║ (gilbert@esd.dl.nec.com) ║
- ║ ║
- ║ I have arranged the code in a flexible way so it is reusable ║
- ║ with other applications. Network support exists within ser4 ║
- ║ but since I do not have a network to test with, I left it out. ║
- ║ If you would like to contribute code for this module, mail me ║
- ║ ║
- ║ The packet reading/writing routines have been omitted. You ║
- ║ will have to design your own packet structure which suits your ║
- ║ application. You may want to look at the original ser4 source ║
- ║ code for some ideas. ║
- ╚═════════════════════════════════════════════════════════════════╝
- */
-
- static struct {
- char patch_id[8];
- char fname[12];
- float version;
- } patch_struct = {"WGTPATCH", "wlink", 1.0} ;
-
- #define WLINK_NOVECTOR 0x67
- #define WLINK_8250_UART 0
- #define WLINK_16550_UART 1
-
- #define TRANSMIT_HOLDING_REGISTER 0x00
- #define RECEIVE_BUFFER_REGISTER 0x00
- #define INTERRUPT_ENABLE_REGISTER 0x01
- #define IER_RX_DATA_READY 0x01
- #define IER_TX_HOLDING_REGISTER_EMPTY 0x02
- #define IER_LINE_STATUS 0x04
- #define IER_MODEM_STATUS 0x08
- #define INTERRUPT_ID_REGISTER 0x02
- #define IIR_MODEM_STATUS_INTERRUPT 0x00
- #define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02
- #define IIR_RX_DATA_READY_INTERRUPT 0x04
- #define IIR_LINE_STATUS_INTERRUPT 0x06
- #define FIFO_CONTROL_REGISTER 0x02
- #define FCR_FIFO_ENABLE 0x01
- #define FCR_RCVR_FIFO_RESET 0x02
- #define FCR_XMIT_FIFO_RESET 0x04
- #define FCR_RCVR_TRIGGER_LSB 0x40
- #define FCR_RCVR_TRIGGER_MSB 0x80
- #define FCR_TRIGGER_01 0x00
- #define FCR_TRIGGER_04 0x40
- #define FCR_TRIGGER_08 0x80
- #define FCR_TRIGGER_14 0xc0
- #define LINE_CONTROL_REGISTER 0x03
- #define LCR_WORD_LENGTH_MASK 0x03
- #define LCR_WORD_LENGTH_SELECT_0 0x01
- #define LCR_WORD_LENGTH_SELECT_1 0x02
- #define LCR_STOP_BITS 0x04
- #define LCR_PARITY_MASK 0x38
- #define LCR_PARITY_ENABLE 0x08
- #define LCR_EVEN_PARITY_SELECT 0x10
- #define LCR_STICK_PARITY 0x20
- #define LCR_SET_BREAK 0x40
- #define LCR_DLAB 0x80
- #define MODEM_CONTROL_REGISTER 0x04
- #define MCR_DTR 0x01
- #define MCR_RTS 0x02
- #define MCR_OUT1 0x04
- #define MCR_OUT2 0x08
- #define MCR_LOOPBACK 0x10
- #define LINE_STATUS_REGISTER 0x05
- #define LSR_DATA_READY 0x01
- #define LSR_OVERRUN_ERROR 0x02
- #define LSR_PARITY_ERROR 0x04
- #define LSR_FRAMING_ERROR 0x08
- #define LSR_BREAK_DETECT 0x10
- #define LSR_THRE 0x20
- #define MODEM_STATUS_REGISTER 0x06
- #define MSR_DELTA_CTS 0x01
- #define MSR_DELTA_DSR 0x02
- #define MSR_TERI 0x04
- #define MSR_DELTA_CD 0x08
- #define MSR_CTS 0x10
- #define MSR_DSR 0x20
- #define MSR_RI 0x40
- #define MSR_CD 0x80
- #define DIVISOR_LATCH_LOW 0x00
- #define DIVISOR_LATCH_HIGH 0x01
- #define CLOCK_FREQUENCY 1843200 /* 1.8432 Mhz */
-
- short uart_type;
-
- #define BUFFERSIZE 4096
- /* BUFFERSIZE must be a power of 2 */
-
- typedef struct
- {
- short head, tail; // bytes are put on head and pulled from tail
- short size;
- unsigned char data[BUFFERSIZE];
- } transferbuffer;
-
- union REGS regs;
- struct SREGS sregs;
-
- void (__interrupt __far *oldirqvect) (void);
- short irqintnum;
-
- transferbuffer buffer_in, buffer_out;
-
- short line_status = -1;
-
- void __interrupt isr8 (void);
- void __interrupt isr16 (void);
-
- /* Modem variables */
- short pulsedial = 0;
- short usemodem = 0;
-
- struct {
- char modem_init [257];
- char modem_hangup [257];
- unsigned long baud_rate;
- short com_port;
- short irq_num;
- short uart;
- short uarttype;
- short vector;
- } link_info;
-
-
-
-
- void *FIRSTMEG (void *x)
- {
- return (void *)((unsigned short)(x) + (((unsigned long)(x)>>12) & 0xffff0));
- }
-
-
- /* Empties the incoming buffer */
- void wlink_flush_incoming (void)
- {
- buffer_in.tail = buffer_in.head;
- buffer_in.size = 0;
- }
-
- /* Empties the outgoing buffer */
- void wlink_flush_outgoing (void)
- {
- buffer_out.tail = buffer_out.head;
- buffer_out.size = 0;
- }
-
-
- /* Finds out what kind of UART is installed. */
- void wlink_getuart (void)
- {
- char *system_data;
- static short ISA_uarts[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
- static short ISA_IRQs[] = {4, 3, 4, 3};
- static short MCA_uarts[] = {0x03f8, 0x02f8, 0x3220, 0x3228};
- static short MCA_IRQs[] = {4, 3, 3, 3};
-
- segread ( &sregs);
-
- regs.h.ah = 0xc0;
- int386x (0x15, ®s, ®s, &sregs);
- if (regs.w.cflag)
- {
- if (link_info.irq_num == -1)
- link_info.irq_num = ISA_IRQs[link_info.com_port - 1];
- if (link_info.uart == -1)
- link_info.uart = ISA_uarts[link_info.com_port - 1];
- return;
- }
-
- system_data = (char *) (((long) sregs.es << 16) + regs.w.bx);
- if (system_data[5] & 0x02)
- {
- if (link_info.irq_num == -1)
- link_info.irq_num = MCA_IRQs[link_info.com_port-1];
- if (link_info.uart == -1)
- link_info.uart = MCA_uarts[link_info.com_port-1];
- }
- else
- {
- if (link_info.irq_num == -1)
- link_info.irq_num = ISA_IRQs[link_info.com_port-1];
- if (link_info.uart == -1)
- link_info.uart = ISA_uarts[link_info.com_port-1];
- }
- }
-
-
- /* Finds out what interrupt vector is being used. */
- void wlink_getvector (void)
- {
- unsigned char *vectorptr;
- unsigned char *vectorptr2;
- unsigned char readbyte;
-
- /* Get an interrupt vector if not already set */
- if (link_info.vector == -1)
- {
- for (link_info.vector = 0x60; link_info.vector <= 0x66; link_info.vector++)
- {
- vectorptr = (void *)(link_info.vector * 4);
- vectorptr = (unsigned char *)FIRSTMEG(vectorptr);
- vectorptr2 = (unsigned char *)FIRSTMEG(*vectorptr);
- readbyte = *vectorptr2;
-
- if ((!(vectorptr2)) || (readbyte == 0xcf))
- break;
- }
- }
- }
-
- /* 8250 Interrupt. One byte at a time. */
- void __interrupt isr8 (void)
- {
- short c;
-
- _disable ();
-
-
- while (1)
- {
- switch (inp (link_info.uart + INTERRUPT_ID_REGISTER) & 7)
- {
- /* receive exactly one byte */
- case IIR_RX_DATA_READY_INTERRUPT :
- c = inp (link_info.uart + RECEIVE_BUFFER_REGISTER);
- buffer_in.data[buffer_in.head++] = c;
- buffer_in.size++;
- if (buffer_in.head >= BUFFERSIZE)
- buffer_in.head = 0; /* wrap around */
- break;
-
- /* transmit exactly one byte */
- case IIR_TX_HOLDING_REGISTER_INTERRUPT :
- if (buffer_out.size != 0)
- {
- c = buffer_out.data[buffer_out.tail++];
- buffer_out.size--;
- if (buffer_out.tail >= BUFFERSIZE)
- buffer_out.tail = 0; /* wrap around */
- outp (link_info.uart + TRANSMIT_HOLDING_REGISTER, c);
- }
- break;
-
- /* line status */
- case IIR_LINE_STATUS_INTERRUPT :
- line_status = inp (link_info.uart + LINE_STATUS_REGISTER);
- break;
-
- /* done */
- default :
- outp (0x20, 0x20);
- _enable();
- return;
- }
- }
- }
-
-
- /* 16550 interrupt. */
- void __interrupt isr16 (void)
- {
- short c;
- short count;
-
- _disable ();
-
- while (1)
- {
- switch (inp (link_info.uart + INTERRUPT_ID_REGISTER) & 7)
- {
- /* receive */
- case IIR_RX_DATA_READY_INTERRUPT:
- do
- {
- c = inp (link_info.uart + RECEIVE_BUFFER_REGISTER);
- buffer_in.data[buffer_in.head++] = c;
- buffer_in.size++;
- if (buffer_in.head >= BUFFERSIZE)
- buffer_in.head = 0; // wrap around
- } while (inp (link_info.uart + LINE_STATUS_REGISTER) & LSR_DATA_READY );
- break;
-
- /* transmit */
- case IIR_TX_HOLDING_REGISTER_INTERRUPT :
- if (buffer_out.size != 0)
- {
- count = 16;
- do
- {
- c = buffer_out.data[buffer_out.tail++];
- buffer_out.size--;
- if (buffer_out.tail >= BUFFERSIZE)
- buffer_out.tail = 0; /* wrap around */
-
- outp (link_info.uart + TRANSMIT_HOLDING_REGISTER, c);
- } while (--count && buffer_out.size != 0);
- }
- break;
-
- /* line status */
- case IIR_LINE_STATUS_INTERRUPT :
- line_status = inp (link_info.uart + LINE_STATUS_REGISTER);
- break;
-
- /* done */
- default :
- outp (0x20, 0x20);
- _enable();
- return;
- }
- }
- }
-
-
-
- /* Returns a byte out of the incoming buffer. Returns -1 if the buffer
- is empty. */
- short wlink_read_byte (void)
- {
- short c;
-
- if (buffer_in.size == 0)
- return -1;
-
- c = buffer_in.data[buffer_in.tail++];
- buffer_in.size--;
-
- if (buffer_in.tail >= BUFFERSIZE)
- buffer_in.tail = 0; /* wrap around */
-
- return c;
- }
-
-
- /* Writes one byte into the outgoing buffer. */
- void write_byte (unsigned char c)
- {
- buffer_out.data[buffer_out.head++] = c;
- buffer_out.size++;
-
- if (buffer_out.head >= BUFFERSIZE)
- buffer_out.head = 0; /* wrap around */
- }
-
-
- /* Writes a string of bytes into the outgoing buffer. */
- void wlink_write_bytes (unsigned char *buf, int count)
- {
- if (buffer_out.head + count >= BUFFERSIZE)
- /* String would wrap around the buffer */
- {
- while (count--)
- write_byte (*buf++);
- }
- else
- {
- memcpy(buffer_out.data + buffer_out.head, buf, count);
- /* Write all at once */
- buffer_out.head += count;
- buffer_out.size += count;
- }
- }
-
-
- /* Start the write interrupts by sending the first char. */
- void jump_start (void)
- {
- short c;
-
- if (buffer_out.size != 0)
- {
- c = buffer_out.data [buffer_out.tail++];
- buffer_out.size--;
- if (buffer_out.tail >= BUFFERSIZE)
- buffer_out.tail = 0; /* wrap around */
- outp (link_info.uart, c);
- }
- }
-
-
- /* Write a packet of information. */
- void wlink_write_buffer (unsigned char *buffer, unsigned int count)
- {
- /* if this would overrun the buffer, throw everything else out */
- if (buffer_out.size + count > BUFFERSIZE)
- {
- buffer_out.tail = buffer_out.head;
- buffer_out.size = 0;
- }
-
- wlink_write_bytes (buffer, count);
-
- if (inp (link_info.uart + LINE_STATUS_REGISTER) & 0x40)
- jump_start ();
- }
-
-
- /* Initialize the communications port. */
- void wlink_initport (void)
- {
- short mcr;
- short temp;
- unsigned long divisor;
-
- if ((divisor = link_info.baud_rate) == 14400)
- divisor = 19200;
-
- divisor = CLOCK_FREQUENCY / (16 * divisor); /* Calc. divisor */
- outp (link_info.uart + LINE_CONTROL_REGISTER, LCR_DLAB); /* Enable divisor */
- outp (link_info.uart + DIVISOR_LATCH_HIGH, 0); /* Set divisor */
- outp (link_info.uart + DIVISOR_LATCH_LOW, (unsigned char) divisor);
- outp (link_info.uart + LINE_CONTROL_REGISTER, 3); /* Set 8,n,1 */
-
- /* check for a 16550 */
- outp (link_info.uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE + FCR_TRIGGER_04);
- temp = inp (link_info.uart + INTERRUPT_ID_REGISTER);
- if ( ( temp & 0xf8 ) == 0xc0 )
- uart_type = WLINK_16550_UART;
- else
- {
- uart_type = WLINK_8250_UART;
- outp (link_info.uart + FIFO_CONTROL_REGISTER, 0);
- }
-
- link_info.uarttype = uart_type;
- /* prepare for interrupts */
- outp (link_info.uart + INTERRUPT_ENABLE_REGISTER, 0); /* Turn off interrupts */
- mcr = inp (link_info.uart + MODEM_CONTROL_REGISTER); /* Get modem status */
- mcr |= MCR_OUT2; /* Set GPO 2 */
- mcr &= ~MCR_LOOPBACK; /* Turn off loopback test */
- mcr |= MCR_DTR; /* Set DTR */ mcr |= MCR_RTS; /* Set RTS */
- outp (link_info.uart + MODEM_CONTROL_REGISTER, mcr); /* Set modem status */
-
- inp (link_info.uart); /* Clear Rx interrupts */
- inp (link_info.uart + INTERRUPT_ID_REGISTER); /* Clear Tx interrupts */
-
- /* hook the irq vector */
- irqintnum = link_info.irq_num + 8;
-
- oldirqvect = _dos_getvect (irqintnum);
- if (uart_type == WLINK_8250_UART) /* Use different interrupt routines */
- _dos_setvect (irqintnum, isr8);
- else
- _dos_setvect (irqintnum, isr16);
-
- outp (0x20 + 1, inp( 0x20 + 1 ) & ~(1<<link_info.irq_num));
-
- _disable();
-
- /* enable RX and TX interrupts at the uart
- also enable Line Status interrupts to watch for errors. */
-
- outp (link_info.uart + INTERRUPT_ENABLE_REGISTER,
- IER_RX_DATA_READY + IER_TX_HOLDING_REGISTER_EMPTY + IER_LINE_STATUS);
-
- /* enable interrupts through the interrupt controller */
-
- outp (0x20, 0xc2);
- _enable ();
- }
-
-
- /* Close the communications port. */
- void wlink_shutdownport (void)
- {
- outp (link_info.uart + INTERRUPT_ENABLE_REGISTER, 0); /* Turn off interrupts */
- outp (link_info.uart + MODEM_CONTROL_REGISTER, 0); /* Clear modem status */
- outp (link_info.uart + FIFO_CONTROL_REGISTER, 0); /* Clear fifo status */
-
- outp (0x20 + 1, inp (0x20 + 1) | (1<<link_info.irq_num));
-
- _dos_setvect (irqintnum,oldirqvect); /* Return to original interrupt */
- }
-
-
- /* Hangs up the modem */
- void wlink_hangup_modem (void)
- {
- outp (link_info.uart + MODEM_CONTROL_REGISTER,
- inp( link_info.uart + MODEM_CONTROL_REGISTER ) & ~MCR_DTR);
- delay (1250);
- outp (link_info.uart + MODEM_CONTROL_REGISTER,
- inp( link_info.uart + MODEM_CONTROL_REGISTER ) | MCR_DTR);
- wlink_modemcommand("+++");
- delay (1250);
- if (link_info.modem_hangup [0] != '\0')
- wlink_modemcommand (link_info.modem_hangup);
- else
- {
- wlink_modemcommand ("ATH0");
- }
- delay (1250);
- while (wlink_read_byte () != -1);
- }
-
-
- /* Writes a command to the modem */
- void wlink_modemcommand (char *str)
- {
- short i;
- char *ptr;
-
- ptr = str;
- for (i = 0; i < strlen (str); i++)
- {
- wlink_write_buffer (ptr++, 1);
- delay (20);
- }
- wlink_write_buffer ("\r",1);
- }
-
-
- /* Write the modem string and look for an OK message */
- int wlink_initmodem (void)
- {
- if (link_info.modem_init [0] != '\0')
- {
- wlink_modemcommand (link_info.modem_init);
- return (wlink_modemresponse ("OK"));
- }
- return 1;
- }
-
-
-
-
- /* ------------------------------ MODEM Routines ------------------------- */
-
-
- int wlink_modemresponse (char *resp)
- {
- short c;
- short respptr;
- char response[80];
-
- do
- {
- respptr = 0;
-
- do
- {
- while ( _bios_keybrd(1) )
- {
- if ( (_bios_keybrd (0) & 0xff) == 27)
- {
- //printf ("\nModem response aborted.\n");
- //wlink_hangup_modem ();
- return 0;
- }
- }
- c = wlink_read_byte ();
- if (c == -1)
- continue;
- if (c == '\n' || respptr == 79)
- {
- response[respptr] = 0;
- //printf ("%s\n", response);
- break;
- }
- if (c >= ' ')
- {
- response[respptr] = c;
- respptr++;
- }
- } while (1);
-
- } while (strncmp (response, resp, strlen (resp)));
- return 1;
- }
-
-
- int wlink_dial (char *dialstring)
- {
- char cmd[80];
-
- usemodem = 1;
-
- wlink_initmodem ();
-
- if (pulsedial)
- sprintf (cmd,"ATDP%s", dialstring);
- else
- sprintf (cmd,"ATDT%s", dialstring);
-
- wlink_modemcommand (cmd);
- return wlink_modemresponse ("CONNECT");
- }
-
-
- int wlink_answer (void)
- {
- usemodem = 1;
- wlink_initmodem ();
-
- if (! wlink_modemresponse ("RING"))
- return 0;
- wlink_modemcommand ("ATA");
- return wlink_modemresponse ("CONNECT");
- }
-
-
-
-
-
-